﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
using SomeRandomGame.Interfaces;

namespace SomeRandomGame.Screens
{
    public abstract class GameScreen
    {
        private bool _isPopup = false;
        private TimeSpan _transitioningInTime = TimeSpan.Zero;
        private TimeSpan _transitioningOutTime = TimeSpan.Zero;
        private float _transitionPosition = 1;
        private ScreenState _screenState = ScreenState.TransitioningIn;
        private bool _isExiting = false;
        private bool _otherScreenHasFocus;
        private ScreenManager _screenManager;
        private PlayerIndex? _controllingPlayer;

        public TimeSpan TransitioningInTime
        {
            get { return _transitioningInTime; }
            protected set { _transitioningInTime = value; }
        }

        public TimeSpan TransitioningOutTime
        {
            get { return _transitioningOutTime; }
            protected set { _transitioningOutTime = value; }
        }

        public float TransitionPosition
        {
            get { return _transitionPosition; }
            protected set { _transitionPosition = value; }
        }

        public float TransitionAlpha
        {
            get { return 1f - TransitionPosition; }
        }

        public ScreenState ScreenState
        {
            get { return _screenState; }
            protected set { _screenState = value; }
        }

        public bool IsExiting
        {
            get { return _isExiting; }
            protected internal set { _isExiting = value; }
        }

        public bool IsActive
        {
            get
            {
                return !_otherScreenHasFocus &&
                       (_screenState == ScreenState.TransitioningIn ||
                        _screenState == ScreenState.Active);
            }
        }

        public bool IsPopup
        {
            get { return _isPopup; }
            protected set { _isPopup = value; }
        }


        public ScreenManager ScreenManager
        {
            get { return _screenManager; }
            internal set { _screenManager = value; }
        }

        public PlayerIndex? ControllingPlayer
        {
            get { return _controllingPlayer; }
            internal set { _controllingPlayer = value; }
        }

        public virtual void Initialize( IGameManager gameManager ) { }

        public virtual void Update( GameTime gameTime, bool otherScreenHasFocus,
                                                      bool coveredByOtherScreen )
        {
            _otherScreenHasFocus = otherScreenHasFocus;

            if( _isExiting )
            {
                _screenState = ScreenState.TransitioningOut;

                if( !UpdateTransition( gameTime, _transitioningOutTime, 1 ) )
                {
                    ScreenManager.RemoveScreen( this );
                }
            }
            else if( coveredByOtherScreen )
            {
                if( UpdateTransition( gameTime, _transitioningOutTime, 1 ) )
                {
                    _screenState = ScreenState.TransitioningOut;
                }
                else
                {
                    _screenState = ScreenState.Hidden;
                }
            }
            else
            {
                if( UpdateTransition( gameTime, _transitioningOutTime, -1 ) )
                {
                    _screenState = ScreenState.TransitioningOut;
                }
                else
                {
                    _screenState = ScreenState.Active;
                }
            }
        }


        private bool UpdateTransition( GameTime gameTime, TimeSpan time, int direction )
        {
            float transitionDelta;

            if( time == TimeSpan.Zero )
            {
                transitionDelta = 1;
            }
            else
            {
                transitionDelta = (float)( gameTime.ElapsedGameTime.TotalMilliseconds /
                                           time.TotalMilliseconds );
            }

            _transitionPosition += transitionDelta * direction;

            if( ( direction < 0 && _transitionPosition <= 0 ) || ( direction > 0 && _transitionPosition >= 1 ) )
            {
                _transitionPosition = MathHelper.Clamp( _transitionPosition, 0, 1 );
                return false;
            }

            return true;
        }

        public virtual void HandleInput( IInputManager inputManager ) { }
        public virtual void Draw( SpriteBatch spriteBatch, IGameManager gameManager, GameTime gameTime ) { }

        public void ExitScreen()
        {
            if( _transitioningOutTime == TimeSpan.Zero )
            {
                ScreenManager.RemoveScreen( this );
            }
            else
            {
                _isExiting = true;
            }
        }
    }
}
